#include <stdio.h>  // 标准输入输出
#include <unistd.h> // POSIX标准接口

#include "ohos_init.h" // 用于初始化服务(services)和功能(features)
#include "cmsis_os2.h" // CMSIS-RTOS API V2

#include "iot_gpio.h" // OpenHarmony HAL：IoT硬件设备操作接口-GPIO
#include "hi_io.h"    // 海思 Pegasus SDK：IoT硬件设备操作接口-IO

/*=================================define&&Global============================================*/
/* 红绿灯引脚定义*/
#define BUTTON_GPIO 12 // 按钮
#define RED_GPIO 9     // 红色LED
#define GREEN_GPIO 11  // 绿色LED
#define YELLOW_GPIO 10 // 黄色LED

unsigned int Traffic_Light_pins[] = {RED_GPIO, YELLOW_GPIO, GREEN_GPIO}; // Light引脚数组

static void OnButtonPressed(char *arg); // 按钮中断处理函数
/*=================================GPIO初始化==================================================*/
// PB0:GPIO_09 连接红色LED，输出低电平点亮
// PB6:GPIO_11 连接绿色LED，输出低电平点亮
// PB1:GPIO_10 连接黄色LED，输出低电平点亮
// PB7:GPIO_12 连接按钮，低电按下

static void GpioInit(void)
{
    // GPIO初始化
    IoTGpioInit(RED_GPIO | GREEN_GPIO | YELLOW_GPIO);
    IoTGpioInit(BUTTON_GPIO);
    // GPIO模式
    IoTGpioSetDir(RED_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(GREEN_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(YELLOW_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(BUTTON_GPIO, IOT_GPIO_DIR_IN);
    // GPIO复用
    hi_io_set_func(RED_GPIO, HI_IO_FUNC_GPIO_9_GPIO);
    hi_io_set_func(GREEN_GPIO, HI_IO_FUNC_GPIO_11_GPIO);
    hi_io_set_func(YELLOW_GPIO, HI_IO_FUNC_GPIO_10_GPIO);
    hi_io_set_func(BUTTON_GPIO, HI_IO_FUNC_GPIO_12_GPIO);

    // 设置GPIO12为上拉模式（引脚上拉）。
    // 引脚上拉后，在按键没有被按下时，读取到的值为1高电平，在按键按下时，读取到的值为0低电平。
    // 注意：本例不获取GPIO5引脚的输入电平。
    hi_io_set_pull(BUTTON_GPIO, HI_IO_PULL_UP);
    // 注册GPIO12中断处理函数。
    IoTGpioRegisterIsrFunc(BUTTON_GPIO,                  // GPIO-12引脚
                           IOT_INT_TYPE_EDGE,            // 边沿触发
                           IOT_GPIO_EDGE_FALL_LEVEL_LOW, // 下降沿触发
                           OnButtonPressed,              // 中断处理函数
                           NULL);                        // 中断处理函数的参数

    // 设置Light默认电平
    for (int i = 0; i < sizeof(Traffic_Light_pins) / sizeof(Traffic_Light_pins[0]); i++)
    {
        IoTGpioSetOutputVal(Traffic_Light_pins[i], 1);
    }
}

static void LightOne()
{
    // 依次点亮Light
    for (int i = 0; i < sizeof(Traffic_Light_pins) / sizeof(Traffic_Light_pins[0]); i++)
    {
        IoTGpioSetOutputVal(Traffic_Light_pins[i], 0);
        // 等待1s
        usleep(1000 * 1000);
        IoTGpioSetOutputVal(Traffic_Light_pins[i], 1);
        // 等待500ms
        usleep(500 * 1000);
    }
}

// GPIO12的中断处理函数
unsigned int Traffic_Light_cnt = 0; // 计数器
static void OnButtonPressed(char *arg)
{
    (void)arg;
    Traffic_Light_cnt++;
    switch (Traffic_Light_cnt % 4)
    {
    case 0:
        IoTGpioSetOutputVal(Traffic_Light_pins[0], 1);
        IoTGpioSetOutputVal(Traffic_Light_pins[1], 1);
        IoTGpioSetOutputVal(Traffic_Light_pins[2], 1);
        break;
    case 1:
        IoTGpioSetOutputVal(Traffic_Light_pins[0], 0);
        IoTGpioSetOutputVal(Traffic_Light_pins[1], 1);
        IoTGpioSetOutputVal(Traffic_Light_pins[2], 1);
        break;
    case 2:
        IoTGpioSetOutputVal(Traffic_Light_pins[0], 1);
        IoTGpioSetOutputVal(Traffic_Light_pins[1], 0);
        IoTGpioSetOutputVal(Traffic_Light_pins[2], 1);
        break;
    case 3:
        IoTGpioSetOutputVal(Traffic_Light_pins[0], 1);
        IoTGpioSetOutputVal(Traffic_Light_pins[1], 1);
        IoTGpioSetOutputVal(Traffic_Light_pins[2], 0);
        break;
    default:
        IoTGpioSetOutputVal(Traffic_Light_pins[0], 1);
        IoTGpioSetOutputVal(Traffic_Light_pins[1], 1);
        IoTGpioSetOutputVal(Traffic_Light_pins[2], 1);
        break;
    }
}

// 主线程函数
static void *TrafficLightTask(const char *arg)
{
    (void)arg;
    // GPIO初始化函数
    GpioInit();
    // 循环亮灯一次
    LightOne();
    // 输出提示信息
    printf("TrafficLightTask start!\r\n");

    while (1)
    {

        osDelay(10);
    }
}

// 入口函数
static void StartTrafficLightTask(void)
{
    // 定义线程属性
    osThreadAttr_t attr;
    attr.name = "TrafficLightTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024;
    attr.priority = osPriorityNormal;

    // 创建线程
    if (osThreadNew((osThreadFunc_t)TrafficLightTask, NULL, &attr) == NULL)
    {
        printf("Falied to create TrafficLightTask!\n");
    }
}

// 运行入口函数
APP_FEATURE_INIT(StartTrafficLightTask);